package com.cgycms.webdeploy.aop.aspect;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.cgycms.webdeploy.aop.Log;
import com.cgycms.webdeploy.auth.UserModel;
import com.cgycms.webdeploy.common.DeployConstant;
import com.cgycms.webdeploy.controller.BaseController;
import com.cgycms.webdeploy.log.LogModel;
import com.cgycms.webdeploy.log.LogService;
import com.cgycms.webdeploy.storage.DeployConfig;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Objects;
import java.util.ServiceLoader;

/**
 * @ClassName : LogAspect
 * @Description : 日志处理
 * @Author : 王力超
 * @Date: 2020-11-10 14:42
 */
@Aspect
@Component
public class LogAspect extends BaseController {

    private static Logger log = LoggerFactory.getLogger(LogAspect.class);


    @Autowired
    private DeployConfig deployConfig;

    @Pointcut("@annotation(com.cgycms.webdeploy.aop.Log)")
    public void annotationPointCut() {
    }

    @Around("annotationPointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Log action = method.getAnnotation(Log.class);

        LogModel logModel = new LogModel();
        UserModel user;
        if (null != (user = (UserModel) getRequest().getSession().getAttribute(DeployConstant.USER_SESSION_ID))) {
            logModel.setUserName(user.getUserName());
            logModel.setUserNick(user.getNick());
        }
        logModel.setLogDate(DateUtil.now());
        logModel.setExecuteMethod(joinPoint.getSignature().getName());
        logModel.setExecuteClass(joinPoint.getTarget().getClass().getName());
        logModel.setUri(getRequest().getRequestURI());
        logModel.setParam(JSONUtil.toJsonStr(getRequest().getParameterMap()));
        logModel.setTitle(action.value());
        logModel.setType(action.type());
        logModel.setExecute(true);

        Object result = null;
        try {
            result = joinPoint.proceed();
            logModel.setResult(JSONUtil.toJsonStr(result));
            String methodPost = "POST";
            String loginPath = "/login";
            if (methodPost.equals(getRequest().getMethod()) && loginPath.equals(getRequest().getRequestURI())) {
                if (result == DeployConstant.USER_LOGIN_SUCCESS) {
                    logModel.setExecute(true);
                    logModel.setResult("登录成功");
                } else if (result == DeployConstant.USER_LOGIN_CAPTCHA_FAIL) {
                    logModel.setExecute(false);
                    logModel.setResult("验证码失败");
                } else {
                    logModel.setExecute(false);
                    logModel.setResult("账号密码错误");
                }
            }
        } catch (Exception e) {
            logModel.setExecute(false);
            logModel.setErrorMsg(e.getMessage());
            log.error("日志记录时报错！{}",e.getMessage());
        } finally {
            try {
                sendLog(logModel);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("发送日志信息时出现异常！");
            }
        }
        return result;
    }


    /**
     * 发送日志
     * @param logModel 日志对象
     */
    private void sendLog(LogModel logModel) {
        if (!deployConfig.isLogEnable()) {
            return;
        }
        ServiceLoader<LogService> serviceLoader = ServiceLoader.load(LogService.class);
        if (Objects.nonNull(logModel)) {
            Iterator<LogService> iaIterator = serviceLoader.iterator();
            while (iaIterator.hasNext()) {
                iaIterator.next().consumeLog(logModel);
            }
        }
    }

}
